/**
 * Copyright (C), 2015-2020, XXX有限公司
 * FileName: ProcessSZAndXZ
 * Author:   ThinkPad
 * Date:     2020/6/24 17:02
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.jt.www.queue.process;

import com.jt.www.enums.issue.InvoiceTypeEnum;
import com.jt.www.enums.issue.IssueEnum;
import com.jt.www.enums.issue.PolicyEnum;
import com.jt.www.enums.issue.PolicyInterfaceEnum;
import com.jt.www.model.issue.entity.IssuePolicyLogEntity;
import com.jt.www.model.issue.entity.IssueRecordEntity;
import com.jt.www.util.DateUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author xq.wu
 * @Description
 * @create 2020/6/24
 * @since 1.0.0
 */
@Service
public class ProcessSZAndXZ extends ElecPolicyProcess implements InitializingBean {

    public static final Logger log = LoggerFactory.getLogger(ProcessSZAndXZ.class);

    @Override
    public void afterPropertiesSet() throws Exception {
        IssuePolicyIfCodeFactory.register(PolicyInterfaceEnum.CODE_10.getIfCode(), this);
        IssuePolicyIfCodeFactory.register(PolicyInterfaceEnum.CODE_11.getIfCode(), this);
    }

    /**
     * 1实责（全国职业院校学生实习责任保险）  2校责（校方责任保险）
     *
     * @param rootElement
     * @return
     */
    @Override
    public Boolean process(Element rootElement, String ifCode) {
        Element reqPacket = getReqPacket(rootElement);
        Element respPacket = getRespPacket(rootElement);
        String companyCode = reqPacket.element("Head").element("UserId").getStringValue();
        String proCode = null;
        String mainTypeStr = "";
        String currentTime = DateUtils.getCurrentTime();
        Iterator iterator = respPacket.element("Body").elementIterator("Apply");
        // 只有山西地区  有发票
        Iterator iteratorReq = reqPacket.element("Body").elementIterator("Apply");
        String desc = PolicyEnum.getIssueEnum(ifCode).getDesc();
        // 投保单号和出单地区 组装的map
        Map<String, String> map = new HashMap();
        Map<String, String> taxMap = new HashMap();
        Map<String, String> mainTypeMap = new HashMap();
        Map<String, String> proCodeMap = new HashMap();
        while (iteratorReq.hasNext()) {
            Element nextReq = (Element) iteratorReq.next();
            String tbNo = nextReq.element("ApplyId").getStringValue();
            String issuingCompanyId = nextReq.element("IssuingCompanyId").getStringValue();
            String OrganizationCode = nextReq.element("PolicyHolder").element("OrganizationCode").getStringValue();
            String mainType = nextReq.element("MainType").getStringValue();
            proCode = IssueEnum.getProCodeByIfCode(ifCode.concat(mainType));
            mainTypeMap.put(tbNo, mainType);
            proCodeMap.put(tbNo, proCode);
            taxMap.put(tbNo, OrganizationCode);
            map.put(tbNo, issuingCompanyId);
        }
        int size = map.size();// 请求体的集合和响应体的集合 size相等
        int i = 0;
        while (iterator.hasNext()) {
            Element nextResp = (Element) iterator.next();
            // 投保单号
            String tbNo = nextResp.element("ApplyId").getStringValue();
            // 保单号
            String policyNo = nextResp.element("PolicyNo").getStringValue();
            String fee = nextResp.element("Fee").getStringValue();
            proCode = proCodeMap.get(tbNo);
            mainTypeStr = mainTypeMap.get(tbNo);

            // 入库
            // 入库之前首先判断 是否已经入库  根据投保单号判断
            IssueRecordEntity issueRecordEntity = new IssueRecordEntity();
            issueRecordEntity.setApplicationFormCode(tbNo);
            List<IssueRecordEntity> select = issueRecordEntityMapper.select(issueRecordEntity);
            if (select == null || select.size() == 0) {
                issueRecordEntity.setPolicyNo(policyNo);
                issueRecordEntity.setCompanyCode(companyCode);
                issueRecordEntity.setProCode(proCode);
                issueRecordEntity.setReqPacket(reqPacket.asXML());
                issueRecordEntity.setResPacket(respPacket.asXML());
                issueRecordEntity.setSendStatus("1");
                issueRecordEntity.setMainType(mainTypeStr);
                String status = getStatus(respPacket);
                // 数据中心返回 的投保单状态
                issueRecordEntity.setStatus(status);
                issueRecordEntity.setCreateTime(currentTime);
                issueRecordEntity.setUpdateTime(currentTime);
                issueRecordEntity.setIfCode(ifCode);
                issueRecordEntityMapper.insert(issueRecordEntity);
                if ("2".equals(status)) { // 成功
                    // 消费  ： 需要组织报文，去调用接口
                    IssuePolicyLogEntity issuePolicyLogEntity = new IssuePolicyLogEntity();
                    String consumeStatus = "1";
                    issuePolicyLogEntity.setApplicationFormCode(tbNo);
                    issuePolicyLogEntity.setPolicyNo(policyNo);
                    issuePolicyLogEntity.setType("1");
                    issuePolicyLogEntity.setStatus(consumeStatus);
                    issuePolicyLogEntity.setCreateTime(currentTime);
                    issuePolicyLogEntity.setUpdateTime(currentTime);
                    issuePolicyLogEntity.setProCode(proCode);
                    // 组装报文
                    Document doc = DocumentHelper.createDocument();
                    Element info = doc.addElement("POLICYNO");
                    info.addText(policyNo);
                    issuePolicyLogEntity.setParam(info.asXML());
                    issuePolicyLogEntity.setMainType(mainTypeStr);
                    issuePolicyLogEntity.setTimes(0);
                    issuePolicyLogEntity.setIfCode(ifCode);
                    issuePolicyLogEntityMapper.insert(issuePolicyLogEntity);
                    // 只要消息进入消费记录的库，就认为消费成功，修改消息记录表状态,具体有没有成功 记录在消费记录表，有定时任务。
                    issueRecordEntity.setSendStatus("2");
                    issueRecordEntityMapper.updateByPrimaryKeySelective(issueRecordEntity);
                    try {
                        // 请求下载保单，成功更新
                        log.info(DateUtils.getCurrentTime() + desc + "保单号是" + tbNo + "下载保单开始，入参" + info.asXML());
                        String seqNo = Long.toString(Math.abs(new Random().nextLong()));
                        //根据ifCode判断是否调用哪个接口
                        String policy = PolicyEnum.getPolicyOrInvoiceByIfCode(ifCode, "POLICY");
                        String invoice = PolicyEnum.getPolicyOrInvoiceByIfCode(ifCode, "INVOICE");
                        String ebody = null;
                        ResponseEntity<String> responseEntity = dexClient.text("edu", policy, "1.0", seqNo, info.asXML());
                        if (responseEntity != null) {
                            ebody = responseEntity.getBody();

                            log.info(DateUtils.getCurrentTime() + "实责校责保单号是" + tbNo + "下载保单结束，回参" + responseEntity.getStatusCodeValue() + "," + ebody);
                            try {
                                doc = DocumentHelper.parseText(ebody);
                                Element ebodyElement = doc.getRootElement();
                                Element data = ebodyElement.element("data");
                                String fileId = "";
                                if (data == null) {
                                    log.error(desc + "请求下载电子保单失败");
                                    consumeStatus = "3";
                                } else {
                                    consumeStatus = "2";
                                    fileId = data.getStringValue();
                                }
                                issuePolicyLogEntity.setStatus(consumeStatus);
                                // 下载电子保单成功，更新数据库，绑定资源
                                log.info(desc + "下载消息 fileId ：{}", fileId);
                                bindingResources(tbNo, fileId, issuePolicyLogEntity);
                            } catch (Exception e) {
                                log.error(desc + "请求下载电子保单异常", e);
                            }
                        }

                        Map<String, String> invoiceList = getAppcodeInvoiceType(tbNo);
                        // 只有山西地区  有发票
                        String issuingCompanyId = map.get(tbNo);
                        //阳光统保地区山西，金额小于10w默认开具电子发票，别的地区选择电子发票就去开，纸质发票不去开具，金额大于10w元的也不去开具
                        if (("301400".equals(issuingCompanyId) && judgingTheAmount(fee)) || (invoiceList.get("invoiceType").equals(InvoiceTypeEnum.ELECTRONIC_INVOICE.getType()) && judgingTheAmount(fee))) { // 有发票
                            //todo 7-13 11:58
                            // 下载电子发票 拼装参数
                            IssuePolicyLogEntity t = new IssuePolicyLogEntity();
                            consumeStatus = "6";
                            t.setApplicationFormCode(tbNo);
                            t.setPolicyNo(policyNo);
                            t.setType("3");
                            t.setStatus(consumeStatus);
                            t.setCreateTime(currentTime);
                            t.setUpdateTime(currentTime);
                            t.setProCode(proCode);
                            t.setMainType(mainTypeStr);
                            t.setIfCode(ifCode);
                            doc = DocumentHelper.createDocument();
                            // 组装电子发票的报文
                            String serialNo = respPacket.element("Head").element("SeqNo").getStringValue();
                            String taxpayerNo = taxMap.get(tbNo);
                            info = doc.addElement("INSURENCEINFO");
                            doc.setRootElement(info);

                            Element policylist = info.addElement("POLICYLIST");
                            Element ismerge = policylist.addElement("ISMERGE");
                            ismerge.addText("0");
                            Element POLICYINFO = policylist.addElement("POLICYINFO");
                            Element productcode = POLICYINFO.addElement("PRODUCTCODE");
                            if ("1".equals(mainTypeStr)) {// 实责
                                productcode.addText("151901");
                            } else if ("2".equals(mainTypeStr)) {// 校责
                                productcode.addText("151301");
                            }
                            POLICYINFO.addElement("SERIALNO").addText(serialNo);
                            POLICYINFO.addElement("POLICYNO").addText(policyNo);
                            POLICYINFO.addElement("INVOICETYPE").addText("2");
                            POLICYINFO.addElement("TAXPAYERNO").addText(taxpayerNo);
                            //新增购方信息
                            String bankAddress = invoiceList.get("bankAddress");
                            String mobile = invoiceList.get("mobile");
                            String bankName = invoiceList.get("bankName");
                            String bankNo = invoiceList.get("bankNo");
                            POLICYINFO.addElement("BANKADDRESS").addText(StringUtils.isEmpty(bankAddress) ? "" : bankAddress);
                            POLICYINFO.addElement("MOBILE").addText(StringUtils.isEmpty(mobile) ? "" : mobile);
                            POLICYINFO.addElement("BANKNAME").addText(StringUtils.isEmpty(bankName) ? "" : bankName);
                            POLICYINFO.addElement("BANKNO").addText(StringUtils.isEmpty(bankNo) ? "" : bankNo);
                            Element AMOUNT = policylist.addElement("AMOUNT");
                            AMOUNT.addText("1");
                            Element TOTALJYJE = policylist.addElement("TOTALJYJE");
                            TOTALJYJE.addText(fee);
                            t.setParam(info.asXML());
                            t.setTimes(1);
                            issuePolicyLogEntity.setIfCode(ifCode);
                            // 电子发票的消费记录入库
                            issuePolicyLogEntityMapper.insert(t);
                            // 刘高逻辑：直接去下载即可。
                            log.info(DateUtils.getCurrentTime() + desc + "投保单号是" + tbNo + "下载发票开始，入参" + info.asXML());
                            seqNo = Long.toString(Math.abs(new Random().nextLong()));
                            responseEntity = dexClient.text("edu", invoice, "1.0", seqNo, info.asXML());
                            log.info(DateUtils.getCurrentTime() + desc + "投保单号是" + tbNo + "下载发票结束，回参" + responseEntity.getStatusCodeValue() + "," + responseEntity.getBody());
                            if (responseEntity != null) {
                                // 请求200，继续执行
                                if (responseEntity.getStatusCodeValue() != 200) {
                                    log.error(desc + "请求下载电子保单失败");
                                    t.setStatus("6");
                                    t.setTimes(1);
                                    t.setUpdateTime(currentTime);
                                    issuePolicyLogEntityMapper.updateByPrimaryKeySelective(t);
                                } else {
                                    ebody = responseEntity.getBody();
                                    doc = DocumentHelper.parseText(ebody);
                                    Element ebodyElement = doc.getRootElement();
                                    String code = ebodyElement.element("code").getStringValue();
                                    if ("0000".equals(code)) {
                                        String eInvoiceId = ebodyElement.element("data").getStringValue();
                                        t.setStatus("2");
                                        t.setUpdateTime(currentTime);
                                        t.setEInvoiceId(eInvoiceId);
                                        bindInvoice(tbNo, eInvoiceId, t);// todo 07-09 15:12
                                    } else {
                                        t.setStatus("6");
                                        t.setTimes(1);
                                        t.setUpdateTime(currentTime);
                                        issuePolicyLogEntityMapper.updateByPrimaryKeySelective(t);
                                    }
                                }
                            }
                            i++;
                        } else {// 没有发票
                            i++;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        issuePolicyLogEntity.setTimes(1);
                        issuePolicyLogEntity.setStatus("3");
                        issuePolicyLogEntity.setUpdateTime(currentTime);
                        issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
                    }
                } else {
                    status = "3";
                    i++;
                }
            } else {
                log.info("系统时间：" + currentTime + desc + ",投保单号是" + tbNo + "的消息发送重复");
                i++;
            }
            sendEmail(tbNo, "21");
        }
        return true;
    }

    public String getStatus(Element respPacket) {
        String status = respPacket.element("Head").element("ResponseCode").getStringValue();

        if ("0".equals(status)) {
            status = "2";
        } else {
            status = "3";
        }
        return status;
    }
}